#region License
// Copyright 2008-2009 Jeremy Skinner (http://www.jeremyskinner.co.uk)
// 
// Licensed under the Apache License, Version 2.0 (the "License"); 
// you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at 
// 
// http://www.apache.org/licenses/LICENSE-2.0 
// 
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an "AS IS" BASIS, 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
// See the License for the specific language governing permissions and 
// limitations under the License.
// 
// The latest version of this file can be found at http://www.codeplex.com/FluentValidation
#endregion

using System;
using FluentValidation.Internal;


namespace FluentValidation.Tests
{
    using System.Globalization;
    using System.Threading;
    using NUnit.Framework;
// ReSharper disable InconsistentNaming
    [TestFixture]
    public class AbstractValidatorTester
    {
        TestValidator _validator;

        [SetUp]
        public void Setup()
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
            _validator = new TestValidator();
        }

        [Test]

        public void When_the_Validators_pass_then_the_validatorRunner_should_return_true()
        {
            _validator.RuleFor("Forename", x => x.Forename).NotNull();
            _validator.Validate(new Person { Forename = "Jeremy" }).IsValid.ShouldBeTrue();
        }

        [Test]
        public void When_the_validators_fail_then_validatorrunner_should_return_false()
        {
            _validator.RuleFor("Forename", x => x.Forename).NotNull();
            _validator.Validate(new Person()).IsValid.ShouldBeFalse();
        }

        [Test]
        public void When_the_validators_fail_then_the_errors_Should_be_accessible_via_the_errors_property()
        {
            _validator.RuleFor("Forename", x => x.Forename).NotNull();
            var result = _validator.Validate(new Person());
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors.Count.ShouldEqual(1);
        }

        [Test]
        public void Should_validate_public_Field()
        {
            _validator.RuleFor("NameField", x => x.NameField).NotNull();
            var result = _validator.Validate(new Person());
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors.Count.ShouldEqual(1);
        }

        [Test]
        public void WithMessage_should_override_error_message()
        {
            _validator.RuleFor("Forename", x => x.Forename).NotNull().WithMessage("This is a overrid message");
            var result = _validator.Validate(new Person());
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors[0].ErrorMessage.ShouldEqual("This is a overrid message");
        }

        [Test]
        public void WithName_should_override_field_name()
        {
            var current = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            _validator.RuleFor("Forename", x => x.Forename).NotNull().WithName("First Name");
            var result = _validator.Validate(new Person());
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors[0].ErrorMessage.ShouldEqual("'First Name' must not be empty.");
        }

        [Test]
        public void WithPropertyName_should_override_property_name()
        {
            _validator.RuleFor("Surname", x => x.Surname).NotNull().WithPropertyName("foo");
            var result = _validator.Validate(new Person());
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors[0].PropertyName.ShouldEqual("foo");
        }

        [Test]
        public void Should_not_main_state()
        {
            _validator.RuleFor("Forename", x => x.Forename).NotNull();
            _validator.Validate(new Person());
            var result = _validator.Validate(new Person());
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors.Count.ShouldEqual(1);
        }

        [Test]
        public void Should_throw_when_rule_is_null()
        {
            typeof(ArgumentNullException).ShouldBeThrownBy(() => _validator.RuleFor<string>("",null));
        }

        [Test]
        public void Should_throw_when_custom_rule_is_null()
        {
            typeof(ArgumentNullException).ShouldBeThrownBy(() => _validator.Custom(null));
        }

        [Test]
        public void Should_validate_single_property()
        {
            _validator.RuleFor("Forename", x => x.Forename).NotNull();
            _validator.RuleFor("Surname", x => x.Surname).NotNull();
            var result = _validator.Validate(new Person(), new NamedExpression<Person> { Expression = x => x.Surname, Identifier = "Surname" });
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors.Count.ShouldEqual(1);
        }

        [Test]
        public void Should_validate_across_properties()
        {
            _validator.RuleFor("Forename", x => x.Forename).NotEqual(x => x.Surname);

            var person = new Person { Forename = "Dyson", Surname = "Dyson" };
            var result = _validator.Validate(person);
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors.Count.ShouldEqual(1);
        }

        [Test]
        public void Should_validate_single_Field()
        {
            _validator.RuleFor("NameField", x => x.NameField).NotNull();
            var result = _validator.Validate(new Person(), new NamedExpression<Person> { Expression = x => x.NameField, Identifier = "NameField" });
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors.Count.ShouldEqual(1);
        }

        [Test]
        public void Should_be_valid_when_there_are_no_failures_for_single_property()
        {
            _validator.RuleFor("Surname", x => x.Surname).NotNull();
            var result = _validator.Validate(new Person { Surname = "foo" }, new NamedExpression<Person> { Expression = x => x.Surname, Identifier = "Surname" });
            result.IsValid.ShouldBeTrue();
        }

        [Test]
        public void Should_validate_single_property_where_property_as_string()
        {
            _validator.RuleFor("Forename", x => x.Forename).NotNull();
            _validator.RuleFor("Surname", x => x.Surname).NotNull();
            var result = _validator.Validate(new Person(), "Surname");
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors.Count.ShouldEqual(1);
        }

        [Test]
        public void Should_validate_single_property_where_invalid_property_as_string()
        {
            _validator.RuleFor("Forename", x => x.Forename).NotNull();
            _validator.RuleFor("Surname", x => x.Surname).NotNull();
            var result = _validator.Validate(new Person(), "Surname1");
            TestHelpers.OutputErrorsToConsole(result);
            result.Errors.Count.ShouldEqual(0);
        }
// ReSharper restore InconsistentNaming
    }
}

